import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:cloud_phone_manager/Callback/Callback.dart';
import 'package:cloud_phone_manager/utils/ConnectUtils.dart';
import 'package:flutter/cupertino.dart';

class CmdUtils {
  static void connectAdb(String ip, CmdCallback callback) {
    CmdUtils.runCommand("adb connect ${ip}",
        (success, error, process, suListener) {
      callback.call(success, error, process, suListener);
    });
  }

  static void platform(String ip, CmdCallback callback) {
    CmdUtils.runCommand("adb -s ${ip} shell which esd",
        (success, error, process, suListener) {
      if (success != null && success != "DONE" && success.isNotEmpty) {
        callback.call("AM", error, process, suListener);
      } else {
        CmdUtils.runCommand("adb -s ${ip} shell which vc",
                (success, error, process, suListener) {
          if(success == "DONE"){
            return;
          }
              if (success != null && success != "DONE"  && success.isNotEmpty) {
                callback.call("SM", error, process, suListener);
              } else {
                callback.call("OTHER", error, process, suListener);
              }
            });
      }
    });
  }

  static void disconnectAdb(String ip, CmdCallback callback) {
    CmdUtils.runCommand("adb disconnect ${ip}",
        (success, error, process, suListener) {
      callback.call(success, error, process, suListener);
    });
  }

  static void deviceModel(CmdCallback callback) {
    CmdUtils.prop("ro.product.model", (success, error, process, suListener) {
      callback.call(success, error, process, suListener);
    });
  }

  static void deviceSnGetter(CmdCallback callback) {
    CmdUtils.runCommand(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} shell getprop persist.vc.boot.serialno",
        (success, error, process, suListener) {
      callback.call(success, error, process, suListener);
    });
  }

  static void deviceAppsUser(CmdCallback callback) {
    CmdUtils.runCommand(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} shell pm list packages -3",
        (success, error, process, suListener) {
      callback.call(success, error, process, suListener);
    });
  }

  static void deviceApps(CmdCallback callback) {
    CmdUtils.runCommand(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} shell pm list packages",
        (success, error, process, suListener) {
      callback.call(success, error, process, suListener);
    });
  }

  static void deviceProcess(CmdCallback callback) {
    if(ConnectUtils.getInstance().getCurrentChooseDevices()?.platform == "山姆"){
      CmdUtils.runCommand(
          "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} shell ps -a",
              (success, error, process, suListener) {
            callback.call(success, error, process, suListener);
          });
    }else{
      CmdUtils.runCommand(
          "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} shell ps",
              (success, error, process, suListener) {
            callback.call(success, error, process, suListener);
          });
    }
  }

  static void deviceAndroidRelease(CmdCallback callback) {
    CmdUtils.prop("ro.build.version.release",
        (success, error, process, suListener) {
      callback.call(success, error, process, suListener);
    });
  }

  static void deviceCpuAbi(CmdCallback callback) {
    CmdUtils.prop("ro.product.cpu.abi", (success, error, process, suListener) {
      callback.call(success, error, process, suListener);
    });
  }

  static void deviceBattery(CmdCallback callback) {
    CmdUtils.runCommand(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} shell dumpsys battery",
        (success, error, process, suListener) {
      callback.call(success, error, process, suListener);
    });
  }

  static void displaySize(CmdCallback callback) {
    CmdUtils.runCommand(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} shell wm size",
        (success, error, process, suListener) {
      callback.call(success, error, process, suListener);
    });
  }

  static void displayDensity(CmdCallback callback) {
    CmdUtils.runCommand(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} shell wm density",
        (success, error, process, suListener) {
      callback.call(success, error, process, suListener);
    });
  }

  static void deviceAndroidSdkVersion(CmdCallback callback) {
    CmdUtils.prop("ro.build.version.sdk",
        (success, error, process, suListener) {
      callback.call(success, error, process, suListener);
    });
  }

  static void prop(String key, CmdCallback callback) {
    CmdUtils.runCommand(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} shell getprop ${key}",
        (success, error, process, suListener) {
      callback.call(success, error, process, suListener);
    });
  }

  static void screenshotAdbToPhone(
      String outputBitmapName, CmdCallback callback) {
    runCommandByNoWait("mkdir /sdcard/adbManager",
        (success, error, process, successListener) {});
    CmdUtils.runCommand(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} shell screencap -p /sdcard/adbManager/${outputBitmapName}",
        (success, error, process, suListener) {
      callback.call(success, error, process, suListener);
    });
  }

  static void pullFileToComputer(String phoneFilePaath,
      String targetComputerFilePath, CmdCallback callback) {
    CmdUtils.runCommand(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} pull $phoneFilePaath $targetComputerFilePath",
        (success, error, process, successListener) {});
  }

  static void devicesAdbList(CmdCallback callback) {
    CmdUtils.runCommand(
        "adb devices",
        (success, error, process, suListener) =>
            callback.call(success, error, process, suListener));
  }

  static void rootAdb() {
    CmdUtils.runCommandByNoWait(
        "adb root", (success, error, process, suListener) => {});
  }

  static void connectToScrcpy(
      int malv, int size, int fps, CmdCallback callback) {
    CmdUtils.runCommand(
        "scrcpy -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} -b ${malv}M --max-size ${size} --max-fps ${fps}",
        (success, error, process, suListener) {
      callback.call(success, error, process, suListener);
    });
  }

  static void restart() {
    CmdUtils.runCommandByNoWait(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} shell reboot",
        (success, error, process, suListener) {});
  }

  static void powerOff() {
    CmdUtils.runCommandByNoWait(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} shell reboot -p",
        (success, error, process, suListener) {});
  }

  static void recovery() {
    CmdUtils.runCommandByNoWait(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} reboot recovery",
        (success, error, process, suListener) {});
  }

  static void fastboot() {
    CmdUtils.runCommandByNoWait(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} reboot bootloader",
        (success, error, process, suListener) {});
  }

  static void rebootAdb() {
    CmdUtils.runCommandByNoWait(
        "adb kill-server", (success, error, process, suListener) {});
    CmdUtils.runCommandByNoWait(
        "adb start-server", (success, error, process, suListener) {});
  }

  static void launchApp(String package) {
    CmdUtils.runCommandByNoWait(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} shell monkey -p $package -c android.intent.category.LAUNCHER 1",
        (success, error, process, suListener) {});
  }

  static void stopApp(String package) {
    //adb shell am force-stop your.package.name
    CmdUtils.runCommandByNoWait(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} shell am force-stop $package",
        (success, error, process, suListener) {});
  }

  static void killProcess(String id) {
    CmdUtils.runCommandByNoWait(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} shell kill -9 $id",
        (success, error, process, suListener) {});
  }

  static void cleanAppData(String package) {
    //adb shell am force-stop your.package.name
    CmdUtils.runCommandByNoWait(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} shell pm clear $package",
        (success, error, process, suListener) {});
  }

  static void cleanAppCache(String package) {
    //adb shell am force-stop your.package.name
    CmdUtils.runCommandByNoWait(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} shell pm clear --cache $package",
        (success, error, process, suListener) {});
  }

  static void uninstallApp(String package) {
    //adb shell am force-stop your.package.name
    CmdUtils.runCommandByNoWait(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} uninstall $package",
        (success, error, process, suListener) {});
  }

  static void installApp(String path, CmdCallback callback) {
    String tmpPath = path;
    CmdUtils.runCommand(
        'adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} install $tmpPath',
        (success, error, process, suListener) {
      callback.call(success, error, process, suListener);
    });
  }

  static void dateForDevice(CmdCallback callback) {
    CmdUtils.runCommand(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} shell date +%Y-%m-%d\\\ %H:%M:%S",
        (success, error, process, suListener) {
      callback.call(success, error, process, suListener);
    });
  }

  static void logcat(String para, CmdCallback callback) {
    CmdUtils.runCommand(
        "adb -s ${ConnectUtils.getInstance().getCurrentChooseDevices()?.name ?? ""} logcat $para",
        (success, error, process, suListener) {
      callback.call(success, error, process, suListener);
    });
  }

  /// 运行cmd命令
  static Future<Process> runCommand(
      String command, CmdCallback callback) async {
    if (command != "adb devices") {
      debugPrint(command);
    }
    Process process = await Process.start('cmd.exe', ['/c', command]);
    StreamSubscription<String>? subscription;
    // 获取命令输出
    subscription = process.stdout.transform(utf8.decoder).listen((data) {
      callback.call(data, "", process, subscription);
    }, onDone: () {
      callback.call("DONE", "DONE", process, subscription);
    });

    // 获取命令错误输出
    process.stderr.transform(utf8.decoder).listen((data) {
      callback.call("", data, process, null);
    });
    // 等待命令执行完成
    int exitCode = await process.exitCode;
    return process;
  }

  static Future<String> exe() async {
    // 指定要执行的ADB命令
    String command = 'adb devices';
    // 执行ADB命令
    try {
      ProcessResult result = await Process.run(
          command.split(' ')[0], command.split(' ').sublist(1));
      if (result.exitCode == 0) {
        print('Output: ${result.stdout}');
        return result.stdout;
      } else {
        print('Error: ${result.stderr}');
        return result.stderr;
      }
    } catch (e) {
      print('Error executing command: $e');
      return "error:${e}";
    }
  }

  /// 运行cmd命令
  static Future<Process> runCommandByNoWait(
      String command, CmdCallback callback) async {
    debugPrint(command);
    Process process = await Process.start('cmd.exe', ['/c', command]);
    int exitCode = await process.exitCode;
    callback.call("", "", process, null);
    return process;
  }
}
